#ifndef _CBUFFER_H
#define _CBUFFER_H

#define SAFE_DELETE(p) if (p) { delete p; p =NULL; }
#define SAFE_DELETE_ARRAY(p) if (p) { delete []p; p =NULL; }

template<class T, int dimension>
class CMultiBuffer
{
public:
	CMultiBuffer()
		: m_nForeIndex(0)
		, m_nBackIndex(0)
		, m_nBufferSize(0)
		, m_nDimension(dimension)
	{
		for (int index = 0; index < dimension; ++index)
		{
			m_pBuffer[index] = NULL;
		}
	}
	virtual ~CMultiBuffer()
	{
		Release();
	}
	void Create(int size)
	{
		if (m_nBufferSize == size)
			return;
		m_nForeIndex = 0;
		m_nBackIndex = 0;
		m_nBufferSize = size;
		for (int index = 0; index < dimension; ++index)
		{
			m_pBuffer[index] = new T[size];
			memset(m_pBuffer[index], 0, size);
		}
	}
	void Release()
	{
		for (int index = 0; index < dimension; ++index)
		{
			SAFE_DELETE_ARRAY(m_pBuffer[index]);
		}
		m_nBufferSize = 0;
	}
	T* ForegroundBuffer()
	{
		T* pTemp = m_pBuffer[m_nForeIndex];
		m_nForeIndex = (m_nForeIndex+1) & ~dimension;
		return pTemp;
	}
	T* BackgroundBuffer()
	{
		T* pTemp = m_pBuffer[m_nBackIndex];
		m_nBackIndex = (m_nBackIndex + 1) & ~dimension;
		return pTemp;
	}
	void FillBuffer(const T* const pSrc, int len)
	{
		if (!pSrc) return;
		m_nDataLen[m_nForeIndex] = len;
		T* pDstBuffer = ForegroundBuffer();
		if (!pDstBuffer) return;
		memset(pDstBuffer, 0, m_nBufferSize);
		memcpy_s(pDstBuffer, m_nBufferSize, pSrc, len);
	}
	T* GetBuffer(int &len)
	{
		len = m_nDataLen[m_nBackIndex];
		T* pTemp = BackgroundBuffer();
		return pTemp;
	}
	int BufferSize(){ return m_nBufferSize; }
protected:
	int m_nDimension;
	int m_nBufferSize;
	T* m_pBuffer[dimension];
	int m_nDataLen[dimension];
	int m_nForeIndex;
	int m_nBackIndex;
};

template<class T>
class CDualBuffer : public CMultiBuffer<T, 2>
{

};

#endif